#include "MessengerPanel.h"

#include "MainFrame.h"
#include "TaskBarIcon.h"
#include "LoginPanel.h"
#include "ContactPanel.h"
#include "ContactTree.h"
#include "SessionPanel.h"
#include "SessionEditor.h"
#include "SessionNotebook.h"
#include "MessengerNotebook.h"

#include "FileTransferManager.h"
#include "FileTransferEntry.h"

#include "FileTransferPanel.h"

#include "GlobalConfig.h"

#include "ContactManager.h"
#include "SessionManager.h"

#include "MsnDef.h"
#include "MsnMessenger.h"
#include "MsnSession.h"
#include "MsnContact.h"
#include "MsnEvent.h"
#include "MsnMessage.h"


class NotifyWindow : public wxDialog
{
private:
	wxStaticText* staticText1;
	wxStaticText* staticText2;
	wxStaticText* staticText3;

	wxRadioBox* radioBox;
	wxCheckBox* checkBox;

	wxButton* okButton;
	wxButton* cancelButton;

	MsnMessenger* messenger;
	wxString passport;

public:
	NotifyWindow(MessengerPanel* mp, const wxString& email, const wxString& name)
		:wxDialog(mp, wxID_ANY, wxString(_T("Tuxitty")))
	{

		messenger = mp->GetMessenger();
		passport = email;

		wxString info = name + _T(" (") + email + _T(") ") + _("added you into his/her contact list.");

		staticText1 = new wxStaticText(this, wxID_ANY, info);

		staticText2 = new wxStaticText(this, wxID_ANY, _T(""));
		staticText3 = new wxStaticText(this, wxID_ANY, _T("You want:"));

		wxArrayString strings;
		strings.Add(_("Allow this people to see me online and talk to me"));
		strings.Add(_("Block this people to see me online and talk to me"));

		radioBox = new wxRadioBox(this, wxID_ANY, _T(""), wxDefaultPosition, wxDefaultSize, strings, 2, wxNO_BORDER |wxRA_SPECIFY_ROWS);
		checkBox = new wxCheckBox(this, wxID_ANY, _("Add this people into my contact list"));
		checkBox->SetValue(true);

		okButton = new wxButton(this, wxID_OK, _("OK"));
		cancelButton = new wxButton(this, wxID_CANCEL, _("Cancel"));

		wxBoxSizer* btnSizer = new wxBoxSizer(wxHORIZONTAL);
		btnSizer->Add(okButton, 0, wxALIGN_RIGHT, 0);
		btnSizer->Add(cancelButton, 0, wxALIGN_RIGHT, 0);

		wxBoxSizer* sizer = new wxBoxSizer(wxVERTICAL);
		sizer->Add(staticText1, 0, wxLEFT | wxRIGHT | wxTOP, 10);
		sizer->Add(staticText2, 0, wxLEFT | wxRIGHT, 10);
		sizer->Add(staticText3, 0, wxLEFT | wxRIGHT, 10);
		sizer->Add(radioBox, 0, wxLEFT | wxRIGHT | wxEXPAND, 20);
		sizer->Add(checkBox, 0, wxLEFT | wxTOP, 10);
		sizer->Add(btnSizer, 0, wxALIGN_RIGHT | wxALL, 10);
		SetSizer(sizer);

		Fit();
		Show();
	}
	
	~NotifyWindow()
	{
		DEBUG(_T("~NotifyWindow"));
	}

	void OnClose(wxCloseEvent &event)
	{
		Destroy();
		//this->Show(false);
	}

	void OnOk(wxCommandEvent& event)
	{
		if(messenger->IsAlive()){
			if(checkBox->IsChecked()){
				messenger->AddContactToForwardList(passport);
			}

			if(radioBox->GetSelection() == 0){
				messenger->AddContactToAllowedList(passport);
			}else{
				messenger->BlockContact(passport);
			}
		}

		Destroy();
	}

	void OnCancel(wxCommandEvent& event)
	{
		Destroy();
	}

DECLARE_EVENT_TABLE()

};


BEGIN_EVENT_TABLE(NotifyWindow, wxDialog)

	EVT_CLOSE(    NotifyWindow::OnClose)
	EVT_BUTTON(wxID_OK, NotifyWindow::OnOk)
	EVT_BUTTON(wxID_CANCEL, NotifyWindow::OnCancel)

END_EVENT_TABLE()




DEFINE_EVENT_TYPE(EVT_MESSENGER_PANEL_CLOSED);

int ID_TIMER_PING = wxNewId();
int ID_TIMER_CHECK = wxNewId();

BEGIN_EVENT_TABLE(MessengerPanel, wxPanel)

	EVT_TIMER(ID_TIMER_PING, MessengerPanel::OnTimerPing)
	EVT_TIMER(ID_TIMER_CHECK, MessengerPanel::OnTimerCheck)

	EVT_NOTEBOOK_PAGE_CHANGED(wxID_ANY,			MessengerPanel::OnSessionNotebookChanged)
   
	EVT_COMMAND(wxID_ANY, EVT_MSN_SERVER_CONNECTION_FAILED, MessengerPanel::OnConnectionFailed)

	EVT_COMMAND(wxID_ANY, EVT_MSN_SERVER_AUTHETICATION_FAILED, MessengerPanel::OnAuthenticationFailed)

	EVT_COMMAND(wxID_ANY, EVT_MSN_SERVER_CONNECTION_BROKEN, MessengerPanel::OnConnectionBroken)

	EVT_COMMAND(wxID_ANY, EVT_MSN_SERVER_SIGNED_IN, MessengerPanel::OnSignedIn)
	EVT_COMMAND(wxID_ANY, EVT_MSN_SERVER_SIGNED_OUT, MessengerPanel::OnSignedOut)

	EVT_COMMAND(wxID_ANY, EVT_MSN_USER_STATUS_CHANGED, MessengerPanel::OnUserStatusChanged)
	EVT_COMMAND(wxID_ANY, EVT_MSN_USER_NAME_CHANGED, MessengerPanel::OnUserNameChanged)
	
	EVT_COMMAND(wxID_ANY, EVT_MSN_SYNCHRONIZATION_FINISHED, MessengerPanel::OnContactSynchronizationFinished)

	EVT_COMMAND(wxID_ANY, EVT_MSN_CONTACT_NAME_CHANGED, MessengerPanel::OnContactNameChanged)
	EVT_COMMAND(wxID_ANY, EVT_MSN_CONTACT_STATUS_CHANGED, MessengerPanel::OnContactStatusChanged)

	EVT_COMMAND(wxID_ANY, EVT_MSN_CONTACT_ADDED, MessengerPanel::OnContactAdded)

	EVT_COMMAND(wxID_ANY, EVT_MSN_CONTACT_ADDED_TO_GROUP, MessengerPanel::OnContactAddedToGroup)

	EVT_COMMAND(wxID_ANY, EVT_MSN_CONTACT_ADDED_TO_REVERSED_LIST, MessengerPanel::OnContactAddedToReversedList)
	EVT_COMMAND(wxID_ANY, EVT_MSN_CONTACT_ADDED_TO_BLOCKED_LIST, MessengerPanel::OnContactAddedToBlockedList)
	

	EVT_COMMAND(wxID_ANY, EVT_MSN_CONTACT_REMOVED, MessengerPanel::OnContactRemoved)
	EVT_COMMAND(wxID_ANY, EVT_MSN_CONTACT_REMOVED_FROM_GROUP, MessengerPanel::OnContactRemovedFromGroup)
	EVT_COMMAND(wxID_ANY, EVT_MSN_CONTACT_REMOVED_FROM_BLOCKED_LIST, MessengerPanel::OnContactRemovedFromBlockedList)
	
	EVT_COMMAND(wxID_ANY, EVT_MSN_GROUP_ADDED, MessengerPanel::OnGroupAdded)
	EVT_COMMAND(wxID_ANY, EVT_MSN_GROUP_REMOVED, MessengerPanel::OnGroupRemoved)
	EVT_COMMAND(wxID_ANY, EVT_MSN_GROUP_RENAMED, MessengerPanel::OnGroupRenamed)


	EVT_COMMAND(wxID_ANY, EVT_MSN_SESSION_CONTACT_JOINED, MessengerPanel::OnSessionContactJoined)
	EVT_COMMAND(wxID_ANY, EVT_MSN_SESSION_CONTACT_LISTED, MessengerPanel::OnSessionContactListed)
	EVT_COMMAND(wxID_ANY, EVT_MSN_SESSION_CONTACT_LEFT, MessengerPanel::OnSessionContactLeft)

	EVT_COMMAND(wxID_ANY, EVT_MSN_CONTROL_MESSAGE_RECEIVED, MessengerPanel::OnControlMessageReceived)

	EVT_COMMAND(wxID_ANY, EVT_MSN_INSTANT_MESSAGE_RECEIVED, MessengerPanel::OnInstantMessageReceived)

	EVT_COMMAND(wxID_ANY, EVT_MSN_INSTANT_MESSAGE_FAILED, MessengerPanel::OnInstantMessageFailed)

	EVT_COMMAND(wxID_ANY, EVT_MSN_FILE_INVITE_SENT, MessengerPanel::OnFileInviteSent)
	EVT_COMMAND(wxID_ANY, EVT_MSN_FILE_INVITE_RECEIVED, MessengerPanel::OnFileInviteReceived)

	
	EVT_COMMAND(wxID_ANY, EVT_MSN_FILE_TRANSFER_STARTED, MessengerPanel::OnFileTransferStarted)
//	EVT_COMMAND(wxID_ANY, EVT_MSN_FILE_TRANSFER_UPDATED, MessengerPanel::OnFileTransferUpdated)
	EVT_COMMAND(wxID_ANY, EVT_MSN_FILE_TRANSFER_DONE, MessengerPanel::OnFileTransferDone)
	EVT_COMMAND(wxID_ANY, EVT_MSN_FILE_TRANSFER_FAILED, MessengerPanel::OnFileTransferFailed)
	EVT_COMMAND(wxID_ANY, EVT_MSN_FILE_TRANSFER_CANCELLED, MessengerPanel::OnFileTransferCancelled)

	EVT_FILE_TRANSFER(EVT_MSN_FILE_TRANSFER_UPDATED, MessengerPanel::OnFileTransferUpdated)

END_EVENT_TABLE()

MessengerPanel::MessengerPanel(wxWindow* parent)
	:wxPanel(parent, wxID_ANY)
{
	messengerNotebook = (MessengerNotebook*) parent;	

	pingTimer = NULL;
	checkTimer = NULL;

	contactPanel = NULL;
	sessionNotebook = NULL;

	messenger = new MsnMessenger();
	messenger->RegisterEventListener(this);

	CreateUI();
}

MessengerPanel::~MessengerPanel()
{
	//do this to avoid memory error or sessionManager in messenger will be deleted first 
	if(sessionNotebook){
		sessionNotebook->DeleteAllPages();
	}

	StopTimer();

	wxDELETE(messenger);

	wxCommandEvent event(EVT_MESSENGER_PANEL_CLOSED, -1);
	App::GetMainFrame()->AddPendingEvent(event);
}

void MessengerPanel::StartTimer()
{
	pingTimer = new wxTimer(this, ID_TIMER_PING);
	checkTimer = new wxTimer(this, ID_TIMER_CHECK);

	pingTimer->Start(60 * 1000);
	checkTimer->Start(60 * 1000);
}

void MessengerPanel::StopTimer()
{
	if(pingTimer != NULL ){
		pingTimer->Stop();
		wxDELETE(pingTimer);
	}

	if(checkTimer != NULL){
		checkTimer->Stop();	
		wxDELETE(checkTimer);
	}
}

void MessengerPanel::CreateUI()
{
	splitter = new wxSplitterWindow(this, -1, wxDefaultPosition, wxSize(600,600), wxSP_BORDER  |wxSP_LIVE_UPDATE );
	//splitter->SetForegroundColour(*wxWHITE);

    leftPanel = new wxPanel(splitter,wxID_ANY, wxDefaultPosition, wxDefaultSize);

	loginPanel = new LoginPanel(this);
    loginPanel->emailTextCtrl->SetValue(GlobalConfig::GetRecentUser());

    wxBoxSizer* leftSizer = new wxBoxSizer(wxVERTICAL);
    leftSizer->Add(loginPanel, 1, wxEXPAND);
    leftPanel->SetSizer(leftSizer);


	sessionNotebook = new SessionNotebook(splitter);
	//wxPanel* rightPanel = new wxPanel(splitter,wxID_ANY);
	//sessionNotebook->SetBackgroundColour(SystemUtil::GetDefaultBackgroundColor());

	splitter->SetSashGravity(0);
	splitter->SplitVertically(leftPanel, sessionNotebook, 200);
	splitter->SetMinimumPaneSize(100);

	wxBoxSizer* sizer = new wxBoxSizer(wxVERTICAL);
    sizer->Add(splitter, 1, wxEXPAND);
   
	this->SetSizer(sizer);

}

void MessengerPanel::UpdateUIText()
{
	loginPanel->UpdateUIText();

	if(contactPanel != NULL){
		contactPanel->UpdateUIText();
	}

	for(unsigned int i=0; i < sessionNotebook->GetPageCount(); i++){
		SessionPanel* panel = (SessionPanel*)sessionNotebook->GetPage(i);
		panel->UpdateUIText();
    }

}

void MessengerPanel::LocateFocus()
{
	if(loginPanel->IsShown()){
		if(loginPanel->emailTextCtrl->IsEmpty()){
			loginPanel->emailTextCtrl->SetFocus();
		}else if(loginPanel->passwordTextCtrl->IsEmpty()){
			loginPanel->passwordTextCtrl->SetFocus();
		}else{
			loginPanel->okButton->SetFocus();
		}

		return;
	}
	
	if(sessionNotebook->GetPageCount()>0){
		SessionPanel* panel = (SessionPanel*)sessionNotebook->GetPage(sessionNotebook->GetSelection());

		panel->sessionEditor->SetFocus();
	}
}


void MessengerPanel::SwitchControlPanel()
{
	DEBUG(_T("SwitchControlPanel"));

    if(IsAlive()){
        loginPanel->Hide();
        if(contactPanel){
			contactPanel->Show();
		}
    }else{
		if(contactPanel){
			contactPanel->Hide();
		}
        loginPanel->Show();
		loginPanel->UpdateUI();
    }

    leftPanel->GetSizer()->Layout();
}


void MessengerPanel::SignIn(const wxString& passport, const wxString& password, const wxString& status)
{
//	wxDELETE(messenger);
	
//	messenger = new MsnMessenger();
//	messenger->RegisterEventListener(this);

	messenger->SignIn(passport, password, status);
}

void MessengerPanel::SignOut()
{
	messenger->SignOut();

	SwitchControlPanel();

	StopTimer();

	EnableSessionPanel(false);

	messengerNotebook->UpdatePanelImage(this, ICON_CONTACT_OFFLINE);

	App::GetMainFrame()->UpdateUIWhenUserSignOut();

}

void MessengerPanel::OnConnectionFailed(wxCommandEvent& event)
{
	loginPanel->UpdateUI();
}

void MessengerPanel::OnAuthenticationFailed(wxCommandEvent& event)
{
	loginPanel->UpdateUI();
}

void MessengerPanel::OnConnectionBroken(wxCommandEvent& event)
{
	loginPanel->UpdateUI();

	OnSignedOut(event);
}


void MessengerPanel::OnSignedIn(wxCommandEvent& event)
{
	DEBUG(_T("signed In event"));

	StartTimer();

	MsnContact* user = (MsnContact*)event.GetClientData();

	wxDELETE(contactPanel);
	contactPanel = new ContactPanel(this);

	leftPanel->GetSizer()->Add(contactPanel, 1, wxEXPAND);
	SwitchControlPanel();

	contactPanel->SetUserName(user->GetName());
	contactTree = contactPanel->contactTreeCtrl;

	EnableSessionPanel(true);

	//TODO fire an event
	messengerNotebook->UpdatePanelTitle(this, user->GetPassport());

	App::GetMainFrame()->UpdateUIWhenUserSignIn();

}

void MessengerPanel::OnSignedOut(wxCommandEvent& event)
{
	DEBUG(_T("signed out event"));

	SwitchControlPanel();

	StopTimer();

	messengerNotebook->UpdatePanelImage(this, ICON_CONTACT_OFFLINE);
	
	App::GetMainFrame()->UpdateUIWhenUserSignOut();

	EnableSessionPanel(false);
	
}

void MessengerPanel::OnContactSynchronizationFinished(wxCommandEvent& event)
{
	DEBUG(_T("synchronization finished event"));
	contactTree->LoadContactData();
}

void MessengerPanel::OnUserNameChanged(wxCommandEvent& event)
{
	DEBUG(_T("user name changed event"));

	contactPanel->SetUserName(event.GetString());	
}

void MessengerPanel::OnUserStatusChanged(wxCommandEvent& event)
{
	DEBUG(_T("user status changed event"));

	wxString status = event.GetString();

	contactPanel->SetUserStatus(status);	

	messengerNotebook->UpdatePanelImage(this, MsnDef::GetStatusIconIndex(status));


}

void MessengerPanel::OnContactNameChanged(wxCommandEvent& event)
{
	DEBUG(_T("contact name changed event"));

	MsnContact* contact = (MsnContact*) event.GetClientData();
	contactTree->UpdateContactItemLabel(contact->GetPassport(), contact->GetName());

	//TODO change panel title
}

void MessengerPanel::OnContactStatusChanged(wxCommandEvent& event)
{
	DEBUG(_T("contact status changed event"));

	MsnContact* contact = (MsnContact*) event.GetClientData();

	//update contact item
	contactTree->UpdateContactItemStatus(contact->GetPassport(), contact->GetStatus());

	//update group item with contact amount
	contactTree->UpdateGroupItemForContact(contact);
	
	//update session panel
	SessionPanel* panel = sessionNotebook->FindPanelByPassport(contact->GetPassport());
	if(panel != NULL){
		sessionNotebook->SetPageImage(sessionNotebook->GetPageIndex(panel), MsnDef::GetStatusIconIndex(contact->GetStatus()));
		panel->OnContactStatusChanged(contact);
	}
}

void MessengerPanel::OnContactAdded(wxCommandEvent& event)
{
	DEBUG(_T("contact added event"));

	MsnContact* contact = (MsnContact*) event.GetClientData();
	contactTree->AddContactItem(contact);
	contactTree->UpdateGroupItemForContact(contact);
}

void MessengerPanel::OnContactRemoved(wxCommandEvent& event)
{
	DEBUG(_T("contact removed event"));

	MsnContact* contact = (MsnContact*)event.GetClientData();
	contactTree->DeleteContactItem(contact->GetID());
	contactTree->UpdateGroupItemForContact(contact);
}

void MessengerPanel::OnContactAddedToGroup(wxCommandEvent& event)
{
	DEBUG(_T("contact added to group event"));
	
	MsnContact* contact = (MsnContact*)event.GetClientData();
	contactTree->AddContactItem(contact->GetID(), event.GetString(), contact->GetDisplayName(), contact);
	contactTree->UpdateGroupItemForContact(contact);
}


void MessengerPanel::OnContactAddedToReversedList(wxCommandEvent& event)
{
	DEBUG(_T("contact added to reversed list event"));
	
	wxGetApp().RequestUserAttention();

	MsnContact* contact = (MsnContact*)event.GetClientData();

	NotifyWindow* notifyWIndow = new NotifyWindow(this, contact->GetPassport(), contact->GetName());
}

void MessengerPanel::OnContactAddedToBlockedList(wxCommandEvent& event)
{
	DEBUG(_T("contact added to blocked list event"));
	
	MsnContact* contact = (MsnContact*)event.GetClientData();

	contactTree->UpdateContactItemStatus(contact->GetPassport(), _T("BLK"));
}

void MessengerPanel::OnContactRemovedFromBlockedList(wxCommandEvent& event)
{
	DEBUG(_T("contact removed to blocked list event"));
	
	MsnContact* contact = (MsnContact*)event.GetClientData();

	contactTree->UpdateContactItemStatus(contact->GetPassport(), contact->GetStatus());	
}

void MessengerPanel::OnContactRemovedFromGroup(wxCommandEvent& event)
{
	DEBUG(_T("contact removed from group event"));

	wxString groupID = event.GetString();
	MsnContact* contact = (MsnContact*)event.GetClientData();
	contactTree->DeleteContactItem(contact->GetID(), groupID);
	contactTree->UpdateGroupItem(groupID);
}

void MessengerPanel::OnGroupAdded(wxCommandEvent& event)
{
	DEBUG(_T("group added event"));

	MsnGroup* group = (MsnGroup*) event.GetClientData();
	contactTree->AddGroupItem(group->GetID(), group->GetName());
}

void MessengerPanel::OnGroupRemoved(wxCommandEvent& event)
{
	DEBUG(_T("group removed event"));

	wxString groupID = event.GetString();
	contactTree->DeleteGroupItemByID(groupID);
}

void MessengerPanel::OnGroupRenamed(wxCommandEvent& event)
{
	DEBUG(_T("group renamed event"));
	//TODO
}



void MessengerPanel::OnSessionContactJoined(wxCommandEvent& event)
{
	DEBUG(_T("session contact joined event"));

	MsnSession* session = (MsnSession*)event.GetClientData();
	UpdateSessionTitle(session);
}

void MessengerPanel::OnSessionContactListed(wxCommandEvent& event)
{
	DEBUG(_T("session contact listed event"));

	MsnSession* session = (MsnSession*)event.GetClientData();
	UpdateSessionTitle(session);
}

void MessengerPanel::OnSessionContactLeft(wxCommandEvent& event)
{
	DEBUG(_T("session contact left event"));

	MsnSession* session = (MsnSession*)event.GetClientData();
	UpdateSessionTitle(session);
}

void MessengerPanel::UpdateSessionTitle(MsnSession* session)
{
	SessionPanel* panel = FindSessionPanel(session);

	if(panel != NULL){			
		sessionNotebook->SetPageText(sessionNotebook->GetPageIndex(panel), session->GetSessionTitle());

		if(session->GetContactCount() > 1) {
			sessionNotebook->SetPageImage(sessionNotebook->GetPageIndex(panel), ICON_CONTACT_MULTI);
		}else if(session->GetContactCount() == 1) {
			wxString passport = session->GetContact(0);
			MsnContact* msnContact = messenger->GetContactManager()->GetContact(passport);
			sessionNotebook->SetPageImage(sessionNotebook->GetPageIndex(panel), MsnDef::GetStatusIconIndex(msnContact->GetStatus()));
		}
	}	
}

void MessengerPanel::EnableSessionPanel(bool b)
{
	for(unsigned int i=0; i < sessionNotebook->GetPageCount(); i++){
		SessionPanel* panel = (SessionPanel*)sessionNotebook->GetPage(i);
		panel->EnableChatCtrl(b);
    }		
}


void MessengerPanel::OnControlMessageReceived(wxCommandEvent& event)
{
	DEBUG(_T("control message received event"));

	//TODO chekc whether it's the current session
	if(this == App::GetMainFrame()->GetCurrentMessengerPanel()){
		wxString contact = event.GetString();
		App::GetMainFrame()->SetStatusText(contact + _(" is typing..."), 1);
	}
}

void MessengerPanel::OnInstantMessageReceived(wxCommandEvent& event)
{
	DEBUG(_T("instant message received event"));

	InstantMessageItem* item = (InstantMessageItem*)event.GetClientData();
	MsnSession* session = item->session;
	SessionPanel* panel = FindSessionPanel(session);

	if(panel == NULL){
		panel = OpenSessionPanel(session, false);

		//anyway request user attention here 
		wxGetApp().RequestUserAttention();
	}

	panel->ProcessEvent(event);

	//notify main frame
	App::GetMainFrame()->UpdateUIWhenNewMsgArrive();

}

void MessengerPanel::OnInstantMessageFailed(wxCommandEvent& event)
{
	DEBUG(_T("instant message failed event"));

	MsnSession* session = (MsnSession*)event.GetClientData();
	SessionPanel* panel = FindSessionPanel(session);

	if(panel != NULL){	
		panel->AppendInstantMessageFailed(event.GetString());

		wxGetApp().RequestUserAttention();
	}
}

void MessengerPanel::OnFileInviteSent(wxCommandEvent& event)
{
	DEBUG(_T("file invite sent event"));

	FileTransferEntry* item = (FileTransferEntry*)event.GetClientData();
	MsnSession* session = item->GetSession();
	SessionPanel* panel = FindSessionPanel(session);

	if(panel == NULL){
		panel = OpenSessionPanel(session, false);
	}

	//anything should be done by session panel???
	panel->ProcessEvent(event);

}

void MessengerPanel::OnFileInviteReceived(wxCommandEvent& event)
{
	DEBUG(_T("file invite received event"));

	FileTransferEntry* item = (FileTransferEntry*)event.GetClientData();
	MsnSession* session = item->GetSession();
	SessionPanel* panel = FindSessionPanel(session);

	if(panel == NULL){
		panel = OpenSessionPanel(session, false);

		//anyway request user attention here. seems like the new page operation brings the frame to be active
		wxGetApp().RequestUserAttention();
	}

	//anything should be done by session panel???
	panel->ProcessEvent(event);

	//if not the current messenger panel, change the panel icon
	if(this != messengerNotebook->GetCurrentPage()){
		DEBUG(_T("notify messenger panel that new message arrives"));
		messengerNotebook->SetPageImage(
			messengerNotebook->GetPageIndex(this), ICON_CONTACT_NEWMSG
		);

		panel->SetNewMessage(true);
	}

}

void MessengerPanel::OnFileTransferStarted(wxCommandEvent& event)
{
	DEBUG(_T("file transfer started event"));

	FileTransferEntry* item = (FileTransferEntry*)event.GetClientData();
	MsnSession* session = item->GetSession();
	SessionPanel* panel = FindSessionPanel(session);	

	if(panel != NULL){
		panel->ProcessEvent(event);
	}
}

void MessengerPanel::OnFileTransferUpdated(FileTransferEvent& event)
{
	DEBUG(_T("file transfer updated event"));

	FileTransferEntry* item = (FileTransferEntry*)event.GetClientData();
	MsnSession* session = item->GetSession();
	SessionPanel* panel = FindSessionPanel(session);	

	if(panel != NULL){
		panel->ProcessEvent(event);
	}
}

void MessengerPanel::OnFileTransferDone(wxCommandEvent& event)
{
	DEBUG(_T("file transfer done event"));

	FileTransferEntry* item = (FileTransferEntry*)event.GetClientData();
	MsnSession* session = item->GetSession();
	SessionPanel* panel = FindSessionPanel(session);

	if(panel != NULL){
		panel->ProcessEvent(event);

		wxGetApp().RequestUserAttention();
	}

	
}

void MessengerPanel::OnFileTransferFailed(wxCommandEvent& event)
{
	DEBUG(_T("file transfer failed event"));

	FileTransferEntry* item = (FileTransferEntry*)event.GetClientData();
	MsnSession* session = item->GetSession();
	SessionPanel* panel = FindSessionPanel(session);	

	panel->ProcessEvent(event);
}

void MessengerPanel::OnFileTransferCancelled(wxCommandEvent& event)
{
	DEBUG(_T("file transfer cancelled event"));

	FileTransferEntry* item = (FileTransferEntry*)event.GetClientData();
	MsnSession* session = item->GetSession();
	SessionPanel* panel = FindSessionPanel(session);

	panel->ProcessEvent(event);

	//wxGetApp().RequestUserAttention();
}


SessionPanel* MessengerPanel::OpenSessionPanel(const wxString& contact, bool selected)
{
	DEBUG(_T("open session panel for ")+contact);

	SessionPanel* panel = FindSessionPanel(contact);
	if(panel == NULL){
		DEBUG(_T("create a new session panel"));
		MsnContact* msnContact = messenger->GetContactManager()->GetContact(contact);
		MsnSession* session = messenger->GetSessionManager()->OpenSession(contact);
		panel = new SessionPanel(this, session);

		int pos = sessionNotebook->GetSelection() + 1;

		//!!!the image index here doesn't work, always online icon.
		sessionNotebook->InsertPage(pos, panel, _T(""), selected);
		//!!!have to set image again
		//sessionNotebook->SetPageImage(pos, imgIndex);
		UpdateSessionTitle(session);

	}else{
		sessionNotebook->SelectPanel(panel);
	}

	LocateFocus();

	return panel;
}

SessionPanel* MessengerPanel::OpenSessionPanel(MsnSession* session, bool selected)
{
	DEBUG(_T("open session panel for existing session"));

	SessionPanel* panel = FindSessionPanel(session);
	if(panel == NULL){
		DEBUG(_T("create a new session panel"));
		//int imgIndex = MsnDef::GetStatusIconIndex(msnContact->GetStatus());

		panel = new SessionPanel(this, session);
		int pos = sessionNotebook->GetSelection()+1;
		sessionNotebook->InsertPage(pos, panel, _T(""), selected);
		//!!!have to set image again
		//sessionNotebook->SetPageImage(pos, imgIndex);
		UpdateSessionTitle(session);
	}else{
		panel->AttachSession(session);
		sessionNotebook->SelectPanel(panel);
	}

	LocateFocus();

	return panel;
}


void MessengerPanel::ShowUp(int pageIndex)
{
	if(messenger->IsAlive()){
		int imageIndex = MsnDef::GetStatusIconIndex(messenger->GetUser()->GetStatus());
		messengerNotebook->SetPageImage(pageIndex, imageIndex);
	}

	if(CurrentSessionPanel() != NULL){
		CurrentSessionPanel()->SetNewMessage(false);
	}
}

bool MessengerPanel::HasNewMessage()
{
    for(unsigned int i=0; i < sessionNotebook->GetPageCount(); i++){
		SessionPanel* panel = (SessionPanel*)sessionNotebook->GetPage(i);

		if(panel->HasNewMessage()){
			return true;
		}  
    }
	return false;	
}


SessionPanel* MessengerPanel::CurrentSessionPanel()
{
	return (SessionPanel*)sessionNotebook->GetCurrentPage();
}

SessionPanel* MessengerPanel::FindSessionPanel(const wxString& contact)
{
	MsnSession* session = messenger->GetSessionManager()->FindSessionByPassport(contact);

	if(session != NULL){
		return FindSessionPanel(session);
	}
	return NULL;
}

SessionPanel* MessengerPanel::FindSessionPanel(MsnSession* session)
{
    for(unsigned int i=0; i < sessionNotebook->GetPageCount(); i++){
		SessionPanel* panel = (SessionPanel*)sessionNotebook->GetPage(i);

		if(session == panel->GetSession()){
			return panel;
		}  
    }
	return NULL;
}

void MessengerPanel::OnSessionNotebookChanged(wxNotebookEvent& event)
{

	int pageIndex = event.GetSelection();
	SessionPanel* panel = (SessionPanel*) sessionNotebook->GetPage(pageIndex);	

	//remove the new msg flag
	panel->SetNewMessage(false);

	//get the first one if there're multiple contacts
	wxString passport = panel->GetSession()->GetContact(0);
	MsnMessenger* messenger = panel->GetSession()->GetMessenger();

	//set back the panel icon (mainly to erase newmsg icon)
	if(messenger->IsAlive()){
		MsnContact* contact =messenger->GetContactManager()->GetContact(passport);
		int imageIndex = MsnDef::GetStatusIconIndex(contact->GetStatus());
		sessionNotebook->SetPageImage(pageIndex, imageIndex);

		LocateFocus();
	}
}

void MessengerPanel::OnTimerPing(wxTimerEvent& e)
{
	if(messenger->IsAlive())
		messenger->Ping();
}

void MessengerPanel::OnTimerCheck(wxTimerEvent& e)
{
	SessionManager* sm = messenger->GetSessionManager();
	std::vector<MsnSession*> sessionList = sm->GetSessionList();

	for(std::vector<MsnSession*>::iterator it = sessionList.begin();it != sessionList.end();++it){
		MsnSession* session = *it;
		session->CheckWaitingMessages();
	}
}
